/*
 * Copyright (c) 2025 Huawei Device Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License"),
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * @addtogroup TeeTrusted
 * @{
 *
 * @brief TEE（Trusted Excution Environment）可信执行环境API。
 *
 * 提供安全能力API，例如可信存储、加解密及可信时间等，用于可信应用程序开发。
 *
 * @since 20
 */

/**
 * @file tee_arith_api.h
 *
 * @brief 提供操作大整数的API。
 *
 * @library NA
 * @kit TEEKit
 * @include <TEEKit/tee_arith_api.h>
 * @syscap SystemCapability.Tee.TeeClient
 * @since 20
 * @version 1.0
 */

#ifndef TEE_ARITH_API_H
#define TEE_ARITH_API_H

#include <tee_defines.h>

#ifdef __cplusplus
extern "C" {
#endif

/**
 * @brief 定义大整数类型。
 *
 * @since 20
 */
typedef uint32_t TEE_BigInt;

/**
 * @brief 定义大整数模乘类型。
 *
 * @since 20
 */
typedef uint32_t TEE_BigIntFMM;

/**
 * @brief 定义大整数模乘上下文类型。
 *
 * @since 20
 */
typedef uint32_t TEE_BigIntFMMContext;

/**
 * @brief 获取表示BigInt所需的uint32_t类型数组的大小。
 *
 * @param n 表示TEE_BigInt类型。
 *
 * @return 返回获得的BigInt大小。
 * @since 20
 * @version 1.0
 */
#define TEE_BigIntSizeInU32(n) ((((n) + 31) / 32) + 2)

/**
 * @brief 获取uint32_t类型数组的大小。
 *
 * @param modulusSizeInBits 表示模数大小，单位为比特。
 *
 * @return 返回存储{@link TEE_BigIntFMM}所需的字节数，给定模数的长度为modSizeInBits。
 * @since 20
 * @version 1.0
 */
size_t TEE_BigIntFMMSizeInU32(size_t modulusSizeInBits);

/**
 * @brief 获取表示快速模数上下文所需的uint32_t类型数组的大小。
 *
 * @param modulusSizeInBits 表示模数大小，单位为比特。
 *
 * @return 返回存储TEE_BigIntFMMContext所需的字节数，给定模数的长度为modSizeInBits。
 * @since 20
 * @version 1.0
 */
size_t TEE_BigIntFMMContextSizeInU32(size_t modulusSizeInBits);

/**
 * @brief 初始化TEE_BigInt。
 *
 * @param bigInt 表示要初始化的TEE_BigInt指针。
 * @param len 表示指向TEE_BigInt的内存大小，以uint32_t为单位。

 * @since 20
 * @version 1.0
 */
void TEE_BigIntInit(TEE_BigInt *bigInt, size_t len);

/**
 * @brief 计算快速模数乘法所需的前置条件，并将其存储在上下文中。
 *
 * @param context 表示要初始化的TEE_BigIntFMMContext指针。
 * @param len 表示指向<context>的内存大小，以uint32_t为单位。
 * @param modulus 表示指向模数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntInitFMMContext(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus);

/**
 * @brief 计算快速模数乘法所需的前置条件，并将其存储在上下文中。
 *
 * @param context 表示要初始化的TEE_BigIntFMMContext指针。
 * @param len 表示指向<context>的内存大小，以uint32_t为单位。
 * @param modulus 表示指向模数的指针。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         如果操作失败，则返回其他值。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntInitFMMContext1(TEE_BigIntFMMContext *context, size_t len, const TEE_BigInt *modulus);

/**
 * @brief 初始化TEE_BigIntFMM并将其表示的值设置为零。
 *
 * @param bigIntFMM 表示要初始化的TEE_BigIntFMM指针。
 * @param len 表示指向bigIntFMM的内存大小，以uint32_t为单位。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntInitFMM(TEE_BigIntFMM *bigIntFMM, size_t len);

/**
 * @brief 将八位字符串缓冲区转换为TEE_BigInt格式。
 *
 * @param dest 表示保存结果的TEE_BigInt指针。
 * @param buffer 表示保存整数的八位字符串表示形式的缓冲区指针。
 * @param bufferLen 表示缓冲区长度，以字节为单位。
 * @param sign 表示dest的符号，设置为<b>sign</b>的符号。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_OVERFLOW：为dest分配的内存过小。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntConvertFromOctetString(TEE_BigInt *dest, const uint8_t *buffer, size_t bufferLen, int32_t sign);

/**
 * @brief 将TEE_BigInt格式的整数的绝对值转换为八位字符串。
 *
 * @param buffer 表示输出缓冲区的指针，保存转换后的八位字符串表示形式。
 * @param bufferLen 表示缓冲区长度，以字节为单位。
 * @param bigInt 表示要转换的整数的指针。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_SHORT_BUFFER：输出缓冲区太小，无法容纳八位字符串。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntConvertToOctetString(void *buffer, size_t *bufferLen, const TEE_BigInt *bigInt);

/**
 * @brief 将dest设置为<b>shortVal</b>的值。
 *
 * @param dest 表示保存结果的TEE_BigInt指针。
 * @param shortVal 表示要设置的值。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntConvertFromS32(TEE_BigInt *dest, int32_t shortVal);

/**
 * @brief 将dest设置为src的值，包括src的符号。
 *
 * @param dest 表示保存结果的int32_t指针。
 * @param src 表示要设置的值的指针。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_OVERFLOW：src无法适配到int32_t中。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntConvertToS32(int32_t *dest, const TEE_BigInt *src);

/**
 * @brief 检查op1 > op2、op1 == op2或op1 < op2。
 *
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @return 如果op1 == op2，返回0，如果op1 > op2，返回一个正数。
 * @since 20
 * @version 1.0
 */
int32_t TEE_BigIntCmp(const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 检查op > shortVal、op == shortVal或op < shortVal。
 *
 * @param op 表示第一个操作数的指针。
 * @param shortVal 表示第二个操作数的值。
 *
 * @return 如果op1 == shortVal，返回0，如果op1 > shortVal，返回一个正数。
 * @since 20
 * @version 1.0
 */
int32_t TEE_BigIntCmpS32(const TEE_BigInt *op, int32_t shortVal);

/**
 * @brief 计算|dest| = |op| >> bits。
 *
 * @param dest 表示保存移位结果的TEE_BigInt指针。
 * @param op 表示要移位的操作数的指针。
 * @param bits 表示移位的位数。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntShiftRight(TEE_BigInt *dest, const TEE_BigInt *op, size_t bits);

/**
 * @brief 获取|src|的自然二进制表示中第bitIndex位的值。
 *
 * @param src 表示整数的指针。
 * @param bitIndex 表示要读取的位的偏移量，从最低有效位的偏移0开始。
 *
 * @return 返回|src|中bitIndex位的布尔值。值true表示1，值false表示0。
 * @since 20
 * @version 1.0
 */
bool TEE_BigIntGetBit(const TEE_BigInt *src, uint32_t bitIndex);

/**
 * @brief 获取|src|的自然二进制表示中的位数，即src的大小。
 *
 * @param src 表示整数的指针。
 *
 * @return 如果src为0，返回0，返回src自然二进制表示中的位数。
 * @since 20
 * @version 1.0
 */
uint32_t TEE_BigIntGetBitCount(const TEE_BigInt *src);

/**
 * @brief 将op的自然二进制表示中第bitIndex位设置为1或0。
 *
 * @param op 表示整数的指针。
 * @param bitIndex 表示要设置的位的偏移量，从最低有效位的偏移0开始。
 * @param value 表示要设置的位值。值为true表示1，值为false表示0。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_OVERFLOW：bitIndex位大于op分配的位长度。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntSetBit(TEE_BigInt *op, uint32_t bitIndex, bool value);

/**
 * @brief 将src的值赋给dest。
 *
 * @param dest 表示要赋值的TEE_BigInt指针。
 * @param src 表示源操作数的指针。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_OVERFLOW：dest操作数无法容纳src的值。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntAssign(TEE_BigInt *dest, const TEE_BigInt *src);

/**
 * @brief 将src的绝对值赋给dest。
 *
 * @param dest 表示要赋值的TEE_BigInt指针。
 * @param src 表示源操作数的指针。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_OVERFLOW：dest操作数无法容纳src的值。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntAbs(TEE_BigInt *dest, const TEE_BigInt *src);

/**
 * @brief 计算dest = op1 + op2。
 *
 * @param dest 表示保存op1和op2之和的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算dest = op1 - op2。
 *
 * @param dest 表示保存op1和op2之差的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 对操作数取反：dest = -op。
 *
 * @param dest 表示保存结果-op的TEE_BigInt指针。
 * @param op 表示要取反的操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief 计算dest = op1 * op2。
 *
 * @param dest 表示保存op1和op2之积的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算dest = op * op。
 *
 * @param dest 表示保存op * op结果的TEE_BigInt指针。
 * @param op 表示要平方的操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief 计算dest = op1 + op2。
 *
 * @param dest 表示保存op1和op2之和的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntAdd(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算dest = op1 - op2。
 *
 * @param dest 表示保存op1和op2之差的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSub(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 对操作数取反：dest = -op。
 *
 * @param dest 表示保存结果-op的TEE_BigInt指针。
 * @param op 表示要取反的操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntNeg(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief 计算dest = op1 * op2。
 *
 * @param dest 表示保存op1和op2之积的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntMul(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算dest = op * op。
 *
 * @param dest 表示保存op * op结果的TEE_BigInt指针。
 * @param op 表示要平方的操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSquare(TEE_BigInt *dest, const TEE_BigInt *op);

/**
 * @brief 计算 <b>dest_r</b> 和 <b>dest_q</b>，使得 op1 = dest_q * op2 + dest_r。
 *
 * @param dest_q 指向TEE_BigInt类型的指针，用于存储商。
 * @param dest_r 指向TEE_BigInt类型的指针，用于存储余数。
 * @param op1 指向第一个操作数的指针，即被除数。
 * @param op2 指向第二个操作数的指针，即除数。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_BAD_PARAMETERS：至少有一个参数为null。
 * @since 20
 * @version 1.0
 */
void TEE_BigIntDiv(TEE_BigInt *dest_q, TEE_BigInt *dest_r, const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算 dest = op (mod n)，使得 0 <= dest < n。
 *
 * @param dest 指向TEE_BigInt的指针，用于存储op(mod n)的结果。
 * @param op 指向需要进行模运算的操作数。
 * @param n [IN]指向模数的指针，模数必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief 计算 dest = (op1 + op2) (mod n)。
 *
 * @param dest 指向TEE_BigInt的指针，用于存储(op1 + op2)(mod n)的结果。
 * @param op1 指向第一个操作数。
 * @param op2 指向第二个操作数。
 * @param n 指向模数的指针，模数必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntAddMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief 计算 dest = (op1 - op2) (mod n)。
 *
 * @param dest 指向TEE_BigInt的指针，用于存储(op1 - op2)(mod n)的结果。
 * @param op1 指向第一个操作数。
 * @param op2 指向第二个操作数。
 * @param n 指向模数的指针，模数必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSubMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief 计算 dest = (op1 * op2) (mod n)。
 *
 * @param dest 指向TEE_BigInt的指针，用于存储(op1 * op2)(mod n)的结果。
 * @param op1 指向第一个操作数。
 * @param op2 指向第二个操作数。
 * @param n 指向模数的指针，模数必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntMulMod(TEE_BigInt *dest, const TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n);

/**
 * @brief 计算 dest = (op * op) (mod n)。
 *
 * @param dest 指向TEE_BigInt的指针，用于存储(op * op)(mod n)的结果。
 * @param op 指向操作数的指针。
 * @param n [IN]指向模数的指针，模数必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntSquareMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief 计算dest，使得dest * op = 1 (mod n)。
 *
 * @param dest 表示保存结果(op^–1)(mod n)的TEE_BigInt指针。
 * @param op 表示操作数的指针。
 * @param n [IN]表示模数的指针，必须大于1。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntInvMod(TEE_BigInt *dest, const TEE_BigInt *op, const TEE_BigInt *n);

/**
 * @brief 检查gcd(op1, op2)是否等于1。
 *
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @return 如果gcd(op1, op2) == 1，返回true；如果gcd(op1, op2) != 1，返回false。
 * @since 20
 * @version 1.0
 */
bool TEE_BigIntRelativePrime(const TEE_BigInt *op1, const TEE_BigInt *op2);

/**
 * @brief 计算<b>op1</b>和<b>op2</b>的最大公约数。
 *
 * @param gcd 表示保存op1和op2最大公约数的TEE_BigInt指针。
 * @param u 表示保存第一个系数的TEE_BigInt指针。
 * @param v 表示保存第二个系数的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntComputeExtendedGcd(TEE_BigInt *gcd, TEE_BigInt *u, TEE_BigInt *v, const TEE_BigInt *op1,
                                  const TEE_BigInt *op2);

/**
 * @brief 对op执行概率性素性测试。
 *
 * @param op 表示待测试的候选数字的指针。
 * @param confidenceLevel 表示非定论测试的期望置信度。
 *
 * @return 如果op是合数，返回0。如果op是素数，返回1。\n
 *         如果测试结果不确定但op是合数的概率小于2^(-confidenceLevel)，返回-1。
 * @since 20
 * @version 1.0
 */
int32_t TEE_BigIntIsProbablePrime(const TEE_BigInt *op, uint32_t confidenceLevel);

/**
 * @brief 将src转换为适合进行快速模数乘法的表示形式。
 *
 * @param dest 表示初始化后的TEE_BigIntFMM内存区域的指针。
 * @param src 表示要转换的TEE_BigInt指针。
 * @param n 表示模数的指针。
 * @param context 表示之前使用{@link TEE_BigIntInitFMMContext1}初始化的上下文的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntConvertToFMM(TEE_BigIntFMM *dest, const TEE_BigInt *src, const TEE_BigInt *n,
                            const TEE_BigIntFMMContext *context);

/**
 * @brief 将快速模数乘法表示中的src转换回TEE_BigInt表示形式。
 *
 * @param dest 表示保存转换结果的初始化后的TEE_BigInt内存区域的指针。
 * @param src 表示保存快速模数乘法表示的TEE_BigIntFMM指针。
 * @param n 表示模数的指针。
 * @param context 表示之前使用{@link TEE_BigIntInitFMMContext1}初始化的上下文的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntConvertFromFMM(TEE_BigInt *dest, const TEE_BigIntFMM *src, const TEE_BigInt *n,
                              const TEE_BigIntFMMContext *context);

/**
 * @brief 在快速模数乘法表示中计算dest = op1 * op2。
 *
 * @param dest 表示保存结果op1 * op2的TEE_BigIntFMM指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 * @param n 表示模数的指针。
 * @param context 表示之前使用{@link TEE_BigIntInitFMMContext1}初始化的上下文的指针。
 *
 * @since 20
 * @version 1.0
 */
void TEE_BigIntComputeFMM(TEE_BigIntFMM *dest, const TEE_BigIntFMM *op1, const TEE_BigIntFMM *op2, const TEE_BigInt *n,
                          const TEE_BigIntFMMContext *context);

/**
 * @brief 计算dest = (op1 ^ op2)(mod n)。
 *
 * @param des 表示保存结果(op1 ^ op2)(mod n)的TEE_BigInt指针。
 * @param op1 表示第一个操作数的指针。
 * @param op2 表示第二个操作数的指针。
 * @param n 表示模数的指针。
 * @param context 表示之前使用{@link TEE_BigIntInitFMMContext1}初始化的上下文的指针，或者初始化为null。
 *
 * @return TEE_SUCCESS：操作成功。\n
 *         TEE_ERROR_NOT_SUPPORTED：n的值不被支持。
 * @since 20
 * @version 1.0
 */
TEE_Result TEE_BigIntExpMod(TEE_BigInt *des, TEE_BigInt *op1, const TEE_BigInt *op2, const TEE_BigInt *n,
                            TEE_BigIntFMMContext *context);

#ifdef __cplusplus
}
#endif

#endif
/** @} */